package com.lc.activiti.utils;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.lc.activiti.config.ConstantsPile;
import com.lc.activiti.sys.entity.SysUser;
import com.lc.activiti.utils.redis.RedisUtil;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.http.HttpStatus;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.server.ResponseStatusException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.beans.FeatureDescriptor;
import java.beans.PropertyDescriptor;
import java.util.*;
import java.util.stream.Collectors;

/**
 * Jwt工具类
 * @author: 骆超
 * @date: 2021/5/21 9:43
 */
public class JwtUtil {


    public static HttpServletRequest getRequest() {
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
        return servletRequestAttributes.getRequest();
    }
    public static HttpServletResponse getResponse() {
        ServletWebRequest servletWebRequest = (ServletWebRequest)RequestContextHolder.getRequestAttributes();
        return servletWebRequest.getResponse();
    }
    
    /**
     * 生成签名,2小时后过期
     * @author 骆超
     * @date 2021/5/21
     * @param sysUser 用户对象
     * @return java.lang.String
     */
    public static String sign(SysUser sysUser) {
        //获取存储在redis中的私钥
        String privateKey = RedisUtil.get(ConstantsPile.RSA_PRIVATE_KEY).toString();
        //过期时间 (DateUtil.offset时间偏移参考hutool的工具类)
        Date date = DateUtil.offset(DateUtil.date(), DateField.HOUR, 2);
        Map<String, Object> tokenDataMap = new HashMap<>();
        BeanWrapper bw = new BeanWrapperImpl(sysUser);
        PropertyDescriptor[] pd = bw.getPropertyDescriptors();
        String emptyNames = Arrays.stream(pd).map(FeatureDescriptor::getName).filter(name -> ObjectUtil.isEmpty(bw.getPropertyValue(name))).collect(Collectors.joining(","));
        BeanUtil.copyProperties(sysUser,tokenDataMap,emptyNames.split(","));
        return Jwts.builder().setClaims(tokenDataMap).setExpiration(date).signWith(SignatureAlgorithm.HS512, privateKey).compact();
    }


    /**
     * 通过token获取用户信息
     * @author 骆超
     * @date 2021/5/21
     * @param token token
     * @return com.lc.activiti.sys.entity.SysUser
     */
    public static SysUser getUserByToken(String token) {
        return BeanUtil.mapToBean(getTokenMap(token), SysUser.class, true, new CopyOptions());
    }

    public static SysUser getUser() {
        String token = getRequest().getHeader("token");
        return BeanUtil.mapToBean(getTokenMap(token), SysUser.class, true, new CopyOptions());
    }

    /**
     * 通过token和key值获取键值
     * @author 骆超
     * @date 2021/5/21
     * @param token token
     * @param key 键
     * @return java.lang.Object
     */
    public static Object getObjectByKey(String token,String key) {
        return Objects.requireNonNull(getTokenMap(token)).get(key);
    }

    /**
     * 获取用户信息
     * @author 骆超
     * @date 2021/5/21
     * @param token 参数说明
     * @return java.util.Map<java.lang.String,java.lang.Object>
     */
    private static Map<String, Object> getTokenMap (String token){
        //获取存储在redis中的私钥
        String privateKey = RedisUtil.get(ConstantsPile.RSA_PRIVATE_KEY).toString();
        try {
            return Jwts.parser().setSigningKey(privateKey).parseClaimsJws(token).getBody();
        }catch (Exception e){
            throw new ResponseStatusException(HttpStatus.UNAUTHORIZED);
        }
    }
}
